package com.aqsare;
/*

 * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Oracle or the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */ 

import java.net.*;
import java.io.*;

public class KKMultiServerThread extends Thread {
    private Socket socket = null;
    boolean VERBOSE = true;		 // turn on/off debugging output
    static int BUFFSIZE = 128000;         // how many bytes our incoming buffer can hold

    static int INT_SIZE = 4;
    static int DOUBLE_SIZE = 8;
    static int FLOAT_SIZE = 4;

    byte data[];
    byte buff[];
    static int SIZE = 10;		// how many items in each packet
    static int NUM_PACKS = 3;	// how many repetitions to do

    int port;
    int dataport;
    boolean reverse = false;
    ServerSocket server;
    Socket sock;
    DatagramSocket recv_sock, send_sock;
    String address;

    BufferedInputStream input;
    BufferedOutputStream output;
    
    nextpattern thisparent;
    public KKMultiServerThread(Socket socket,nextpattern thisparent) {
	super("KKMultiServerThread");
	this.socket = socket;
	this.thisparent=thisparent;
    }

    public void run() {
    	port = 5010;
    	dataport = 5011;
    	byte rev[] = new byte[1];
    	buff = new byte[BUFFSIZE];
    	data = new byte[BUFFSIZE];
    	
    	rev[0] = 0;
    	
    	try {
			recv_sock = new DatagramSocket(dataport);
			send_sock = new DatagramSocket();
		} 
		catch (SocketException se) {
			se.printStackTrace();
		}
	try {
		
		input = new BufferedInputStream(socket.getInputStream(), BUFFSIZE);
		output = new BufferedOutputStream(socket.getOutputStream(),BUFFSIZE);

		input.read(rev);
		
		if (VERBOSE) 
			if (rev[0]==1) 
			{
				reverse = true;
				System.out.println("Client:  requested reversed bytes");
			}
			else
				System.out.println("Client:  requested normal byte order");
	  
	
	    String inputLine, outputLine;
	    
	    KnockKnockProtocol kkp = new KnockKnockProtocol();
	    outputLine = kkp.processInput(null);
	    double C[];
		byte D[];

		C = new double[SIZE];
		D = new byte[SIZE];

	    int i =0;
		boolean listening = true;
		 while (i<1)
		{
			//System.out.println("Server, sending bytes, iteration " + i);
		//	mylink.SendBytes(D, SIZE);

			System.out.println("Server, receiving doubles, iteration " + i);
			try{
				char terminal = '#';
				String[] update=this.RecvString(terminal).split(":");
				for (int x=0; x<update.length; x++)
			         System.out.println(update[x]);
				thisparent.updateCurrentPatterns(new Double(update[1]).doubleValue());
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
			System.out.println("Server, received doubles, iteration " + i);
			i++;
		}

	    socket.close();

	} catch (IOException e) {
	    e.printStackTrace();
	}
	
	buff = new byte[BUFFSIZE];
	data = new byte[BUFFSIZE];
	
	
	
	
    }
    
    
    
    public void SendString(String str) throws IOException
    {

 	/* convert our string into an array of bytes */

 	ByteArrayOutputStream bytestream;
 	bytestream = new ByteArrayOutputStream(str.length());

 	DataOutputStream out;
 	out = new DataOutputStream(bytestream);

 	for (int i=0; i<str.length(); i++)
 		out.write((byte) str.charAt(i));

 	output.write(bytestream.toByteArray(), 0, bytestream.size());
 	output.flush();

  	if (VERBOSE) System.out.println("Client: sending '" + str +"'");

 	SendAck();
 	SendAck();
    }

    public void SendBytes(byte vals[], int len) throws IOException
    {
 	if (VERBOSE) 
 	{
 		System.out.print("Client: sending " + len +" bytes: ");
 		for (int i=0; i<len; i++)
 			System.out.print(vals[i] + " ");
 	}

 	output.write(vals, 0, len);
 	output.flush();

  	if (VERBOSE) System.out.println("");

 	RecvAck();
 	SendAck();
    }

    public void SendInts(int vals[], int len) throws IOException
    {
 	if (VERBOSE) System.out.print("Client: sending " + len +" ints: ");

 	/* convert our array of ints into an array of bytes */

 	ByteArrayOutputStream bytestream;
 	bytestream = new ByteArrayOutputStream(len*INT_SIZE);

 	DataOutputStream out;
 	out = new DataOutputStream(bytestream);

 	for (int i=0; i<len; i++)
 	{
 		out.writeInt(vals[i]);
 	 	if (VERBOSE) System.out.print(vals[i]+" ");
 	}	

 	byte byte_array[] = bytestream.toByteArray();

 	if (reverse)
 	{
 		// flip around our bytes if necessary

 		byte flip_array[] = new byte[bytestream.size()];
 		int i, j;

 		for (i=0; i<len; i++)
 		{
 			for (j=0; j<INT_SIZE; j++)
 			{
 				flip_array[(i+1) * INT_SIZE - j - 1] = 
 					byte_array[i * INT_SIZE + j];
 			}
 		}

 		output.write(flip_array, 0, bytestream.size());
 	}
 	else
 		output.write(byte_array, 0, bytestream.size());

 	output.flush();

  	if (VERBOSE) System.out.println("");

 	RecvAck();
 	SendAck();
    }

    public void SendFloats(float vals[], int len) throws IOException
    {
 	if (VERBOSE) System.out.print("Client: sending " + len +" floats: ");

 	/* convert our array of floats into an array of bytes */

 	ByteArrayOutputStream bytestream;
 	bytestream = new ByteArrayOutputStream(len*FLOAT_SIZE);

 	DataOutputStream out;
 	out = new DataOutputStream(bytestream);

 	for (int i=0; i<len; i++)
 	{
 		out.writeFloat(vals[i]);
 	 	if (VERBOSE) System.out.print(vals[i]+" ");
 	}	
 	byte byte_array[] = bytestream.toByteArray();

 	if (reverse)
 	{
 		// flip around our bytes if necessary

 		byte flip_array[] = new byte[bytestream.size()];
 		int i, j;

 		for (i=0; i<len; i++)
 		{
 			for (j=0; j<FLOAT_SIZE; j++)
 			{
 				flip_array[(i+1) * FLOAT_SIZE - j - 1] = 
 					byte_array[i * FLOAT_SIZE + j];
 			}
 		}

 		output.write(flip_array, 0, bytestream.size());
 	}
 	else
 		output.write(byte_array, 0, bytestream.size());

 	output.flush();

  	if (VERBOSE) System.out.println("");

 	RecvAck();
 	SendAck();
    }

    public void SendDoubles(double vals[], int len) throws IOException
    {
 	if (VERBOSE) System.out.print("Client: sending " + len +" doubles: ");

 	/* convert our array of floats into an array of bytes */

 	ByteArrayOutputStream bytestream;
 	bytestream = new ByteArrayOutputStream(len*DOUBLE_SIZE);

 	DataOutputStream out;
 	out = new DataOutputStream(bytestream);

 	for (int i=0; i<len; i++)
 	{
 		out.writeDouble(vals[i]);
 	 	if (VERBOSE) System.out.print(vals[i]+" ");
 	}	

 	byte byte_array[] = bytestream.toByteArray();

 	if (reverse)
 	{
 		// flip around our bytes if necessary

 		byte flip_array[] = new byte[bytestream.size()];
 		int i, j;

 		for (i=0; i<len; i++)
 		{
 			for (j=0; j<DOUBLE_SIZE; j++)
 			{
 				flip_array[(i+1) * DOUBLE_SIZE - j - 1] = 
 					byte_array[i * DOUBLE_SIZE + j];
 			}
 		}

 		output.write(flip_array, 0, bytestream.size());
 	}
 	else
 		output.write(byte_array, 0, bytestream.size());

 	output.flush();

 	if (VERBOSE) System.out.println("");
 	
 	RecvAck();
 	SendAck();
    }

    public void SendDatagram(byte vals[], int len) throws IOException
    {
 	DatagramPacket sendPacket;

 	if (VERBOSE) 
 	{
 		System.out.print("Client: sending datagram of " + len +" bytes: ");
 		for (int i=0; i<len; i++)
 			System.out.print(vals[i] + " ");
 	}

 	sendPacket = new DatagramPacket(vals, len,
 					InetAddress.getByName(address), dataport);
 	send_sock.send(sendPacket);

  	if (VERBOSE) System.out.println("");

    }

    // recv a string from the socket (terminates on terminal char)
    public String RecvString(char terminal) throws IOException
    {
 	char c;
 	String out;

 	// would have liked to use readUTF, but it didn't seem to work
 	// when talking to the c++ server

 	out = new String("");

 	while ((c=(char) input.read())!=terminal)
 		out = out + String.valueOf(c);

  	if (VERBOSE) System.out.println("Client: recv'd '" + out +"'");

 	SendAck();
 	RecvAck();

 	return out;
    }

   public int RecvBytes(byte val[], int maxlen) throws IOException
   {
        int i;
        int totalbytes = 0;
        int numbytes;

 	if (maxlen>BUFFSIZE)
 		System.out.println("Sending more bytes then will fit in buffer!");

 	while (totalbytes < maxlen)
 	{
 		numbytes = input.read(data);

 		// copy the bytes into the result buffer
 		for (i=totalbytes; i<totalbytes+numbytes; i++)
 			val[i] = data[i-totalbytes];

 		totalbytes += numbytes;
 	}

 	if (VERBOSE) 
 	{
 		System.out.print("Client: received " + maxlen + " bytes - ");
 		for (i=0; i<maxlen; i++)
 			System.out.print(val[i]+" ");
 		System.out.println("");
 	}

 	// we now send an acknowledgement to the server to let them
 	// know we've got it

 	SendAck();
 	RecvAck();

 	return maxlen;
   }

   public int RecvInts(int val[], int maxlen) throws IOException
   {
        int i;
        int totalbytes = 0;
        int numbytes;

 	/* for performance, we need to receive data as an array of bytes
 		and then convert to an array of ints, more fun than
 		you can shake a stick at! */

 	if (maxlen*INT_SIZE>BUFFSIZE)
 		System.out.println("Sending more ints then will fit in buffer!");

 	while (totalbytes < maxlen*INT_SIZE)
 	{
 		numbytes = input.read(data);

 		// copy the bytes into the result buffer
 		for (i=totalbytes; i<totalbytes+numbytes; i++)
 			buff[i] = data[i-totalbytes];

 		totalbytes += numbytes;
 	}

 	// now we must convert the array of bytes to an array of ints


 	if (reverse)
 	{
 		// flip around our bytes if necessary

 	        ByteArrayInputStream bytestream_rev;
 		DataInputStream instream_rev;


 		byte flip_array[] = new byte[totalbytes];
 		int j;

 		for (i = 0; i < totalbytes / INT_SIZE; i++)
 		{
 			for (j = 0; j < INT_SIZE; j++)
 			{
 				flip_array[(i+1)*INT_SIZE - j - 1] = 
 					buff[i * INT_SIZE + j];
 			}

 		}

 		bytestream_rev = new ByteArrayInputStream(flip_array);
 		instream_rev = new DataInputStream(bytestream_rev);

 		for (i=0; i<maxlen; i++)
 			val[i] = instream_rev.readInt();

 	}	// end reverse section
 	else
 	{
 	        ByteArrayInputStream bytestream;
 		DataInputStream instream;

 		bytestream = new ByteArrayInputStream(buff);
 		instream = new DataInputStream(bytestream);

 		for (i=0; i<maxlen; i++)
 			val[i] = instream.readInt();
 	}

 	if (VERBOSE) 
 	{
 		System.out.print("Client: received " + maxlen + " ints - ");
 		for (i=0; i<maxlen; i++)
 			System.out.print(val[i]+" ");
 		System.out.println("");
 	}

 	// we now send an acknowledgement to the server to let them
 	// know we've got it

 	SendAck();
 	RecvAck();

 	return maxlen;
   }

   public int RecvDoubles(double val[], int maxlen) throws IOException
   {
        int i;
        int numbytes;
        int totalbytes = 0;

 	/* for performance, we need to receive data as an array of bytes
 		and then convert to an array of ints, more fun than
 		you can shake a stick at! */

 	if (maxlen*8>BUFFSIZE)
 		System.out.println("Sending more doubles then will fit in buffer!");

 	while (totalbytes < maxlen*DOUBLE_SIZE)
 	{
 		numbytes = input.read(data);

 		// copy the bytes into the result buffer
 		for (i=totalbytes; i<totalbytes+numbytes; i++)
 			buff[i] = data[i-totalbytes];

 		totalbytes += numbytes;
 	
 	}

 	// now we must convert the array of bytes to an array of doubles

 	if (reverse)
 	{
 		// flip around our bytes if necessary

 	        ByteArrayInputStream bytestream_rev;
 		DataInputStream instream_rev;


 		byte flip_array[] = new byte[totalbytes];
 		int j;

 		for (i = 0; i < totalbytes / DOUBLE_SIZE; i++)
 		{
 			for (j = 0; j < DOUBLE_SIZE; j++)
 			{
 				flip_array[(i+1)*DOUBLE_SIZE - j - 1] = 
 					buff[i * DOUBLE_SIZE + j];
 			}

 		}

 		bytestream_rev = new ByteArrayInputStream(flip_array);
 		instream_rev = new DataInputStream(bytestream_rev);

 		for (i=0; i<maxlen; i++)
 			val[i] = instream_rev.readDouble();

 	}	// end reverse section
 	else
 	{
 	        ByteArrayInputStream bytestream;
 		DataInputStream instream;

 		bytestream = new ByteArrayInputStream(buff);
 		instream = new DataInputStream(bytestream);

 		for (i=0; i<maxlen; i++)
 			val[i] = instream.readDouble();
 	}

 	if (VERBOSE) 
 	{
 		System.out.print("Client: received " + maxlen + " doubles - ");
 		for (i=0; i<maxlen; i++)
 			System.out.print(val[i]+" ");
 		System.out.println("");
 	}

 	SendAck();
 	RecvAck();

 	return maxlen;
   }

   public int RecvFloats(float val[], int maxlen) throws IOException
   {
        int i;
        int numbytes;
        int totalbytes = 0;

 	/* for performance, we need to receive data as an array of bytes
 		and then convert to an array of ints, more fun than
 		you can shake a stick at! */

 	if (maxlen*FLOAT_SIZE>BUFFSIZE)
 		System.out.println("Sending more doubles then will fit in buffer!");

 	while (totalbytes < maxlen*FLOAT_SIZE)
 	{
 		numbytes = input.read(data);

 		// copy the bytes into the result buffer
 		for (i=totalbytes; i<totalbytes+numbytes; i++)
 			buff[i] = data[i-totalbytes];

 		totalbytes += numbytes;

 	}

 	// now we must convert the array of bytes to an array of ints

 	if (reverse)
 	{
 		// flip around our bytes if necessary

 	        ByteArrayInputStream bytestream_rev;
 		DataInputStream instream_rev;


 		byte flip_array[] = new byte[totalbytes];
 		int j;

 		for (i = 0; i < totalbytes / FLOAT_SIZE; i++)
 		{
 			for (j = 0; j < FLOAT_SIZE; j++)
 			{
 				flip_array[(i+1)*FLOAT_SIZE - j - 1] = 
 					buff[i * FLOAT_SIZE + j];
 			}

 		}

 		bytestream_rev = new ByteArrayInputStream(flip_array);
 		instream_rev = new DataInputStream(bytestream_rev);

 		for (i=0; i<maxlen; i++)
 			val[i] = instream_rev.readFloat();

 	}	// end reverse section
 	else
 	{
 	        ByteArrayInputStream bytestream;
 		DataInputStream instream;

 		bytestream = new ByteArrayInputStream(buff);
 		instream = new DataInputStream(bytestream);

 		for (i=0; i<maxlen; i++)
 			val[i] = instream.readFloat();
 	}


 	if (VERBOSE) 
 	{
 		System.out.print("Client: received " + maxlen + " floats - ");
 		for (i=0; i<maxlen; i++)
 			System.out.print(val[i]+" ");
 		System.out.println("");
 	}

 	SendAck();
 	RecvAck();

 	return maxlen;
   }

   public int RecvDatagram(byte val[], int maxlen) throws IOException
   {
         int i;
         int numbytes;
 	DatagramPacket receivePacket;

 	if (maxlen>BUFFSIZE)
 		System.out.println("Sending more bytes then will fit in buffer!");


 	receivePacket = new DatagramPacket(val, maxlen);
 	recv_sock.receive(receivePacket);

 	numbytes = receivePacket.getLength();

 	if (VERBOSE) 
 	{
 		System.out.print("Client: received " + numbytes + " bytes - ");
 		for (i=0; i<numbytes; i++)
 			System.out.print(val[i]+" ");
 		System.out.println("");
 	}

 	return numbytes;
   }



    // shutdown the socket
    public void Close() throws IOException
    {
 	sock.close();

  	if (VERBOSE) System.out.println("Client: closing socket");
    }

    // send a short ack to the server so they know we are ready for more

    private void SendAck() throws IOException
    {
 	int ack;

 	ack = 0;

 	if (VERBOSE)
 		System.out.println("Sending ack...");

 	output.write(ack);
 	output.flush();

    }

    // recv a short ack from the server so we know they are ready for more

    private void RecvAck() throws IOException
    {
 	int ack;

 	if (VERBOSE)
 		System.out.println("Waiting for ack...");

 	//ack = (int) input.read();

 	if (VERBOSE)
 		System.out.println("Ack recieved.");

    }
 }

